/*
  FirmataMarshaller.h
  Copyright (c) 2006-2008 Hans-Christoph Steiner.  All rights reserved.
  Copyright (C) 2009-2016 Jeff Hoefs.  All rights reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  See file LICENSE.txt for further informations on licensing terms.
*/

#ifndef FirmataMarshaller_h
#define FirmataMarshaller_h

#if defined(__cplusplus) && !defined(ARDUINO)
#include <cstddef>
#include <cstdint>
#else

#include <cstddef>
#include <cstdint>

#endif

#include <nStream.h>

namespace firmata {

    class FirmataMarshaller {
        friend class FirmataClass;

    public:
        /* constructors */
        FirmataMarshaller();

        /* public methods */
        void begin();

        void end();

        /* serial send handling */
        void queryFirmwareVersion(nStream *FirmataStream);

        void queryVersion(nStream *FirmataStream);

        void reportAnalogDisable(nStream *FirmataStream, uint8_t pin);

        void reportAnalogEnable(nStream *FirmataStream, uint8_t pin);

        void reportDigitalPortDisable(nStream *FirmataStream, uint8_t portNumber);

        void reportDigitalPortEnable(nStream *FirmataStream, uint8_t portNumber);

        void sendAnalog(nStream *FirmataStream, uint8_t pin, int16_t value);

        void sendAnalogMappingQuery(nStream *FirmataStream);

        void sendCapabilityQuery(nStream *FirmataStream);

        void sendDigital(nStream *FirmataStream, uint8_t pin, uint8_t value);

        void sendDigitalPort(nStream *FirmataStream, uint8_t portNumber, uint16_t portData);

        void
        sendFirmwareVersion(nStream *FirmataStream, uint8_t major, uint8_t minor, size_t bytec, uint8_t *bytev);

        void sendVersion(nStream *FirmataStream, uint8_t major, uint8_t minor);

        void sendPinMode(nStream *FirmataStream, uint8_t pin, uint8_t config);

        void sendPinStateQuery(nStream *FirmataStream, uint8_t pin);

        void sendString(nStream *FirmataStream, const char *string);

        void sendSysex(nStream *FirmataStream, uint8_t command, size_t bytec, uint8_t *bytev);

        void setSamplingInterval(nStream *FirmataStream, uint16_t interval_ms);

        void systemReset(nStream *FirmataStream);

    private:
        /* utility methods */
        static void reportAnalog(nStream *FirmataStream, uint8_t pin, bool stream_enable);

        void reportDigitalPort(nStream *FirmataStream, uint8_t portNumber, bool stream_enable);

        void sendExtendedAnalog(nStream *FirmataStream, uint8_t pin, size_t bytec, uint8_t *bytev);

        void encodeByteStream(nStream *FirmataStream, size_t bytec, uint8_t *bytev, size_t max_bytes = 0);

        // nStream *FirmataStream = nullptr;
    };

} // namespace firmata

#endif /* FirmataMarshaller_h */
